#pragma  once;

#define PLAT_WIN	1
typedef ULONG_PTR uptr_t;
typedef LONG_PTR sptr_t;

#include "def.h"
#include "ILexer.h"




int inline Min( int a, int b ) {
	if( a > b ) {
		return b;
	}
	return a;
}
int inline  Max( int a, int b ) {
	if( a > b ) {
		return a;
	}
	return b;
}
int inline Clamp( int val, int minVal, int maxVal ) {
	if ( val > maxVal ) {
		val = maxVal;
	}
	if ( val < minVal ) {
		val = minVal;
	}
	return val;
}


namespace soy {
typedef unsigned char byte;
typedef unsigned char uchar;
typedef unsigned int  uint;
typedef unsigned long ulong;

typedef INT32 XYPOS;//x-y position
typedef INT32 NPOS;//index position

typedef void* FontID;
typedef void* SurfaceID;
typedef void* WindowID;
typedef void* MenuID;
typedef void* TickerID;
typedef void* Function;
typedef void* IdlerID;

class Point {
public:
	int x;
	int y;

	explicit Point(int x_=0, int y_=0) : x(x_), y(y_) {
	}

	// Other automatically defined methods (assignment, copy constructor, destructor) are fine

	static Point FromLong(long lpoint);
};

class Rect {
public:
	XYPOS left;
	XYPOS top;
	XYPOS right;
	XYPOS bottom;

	Rect( XYPOS left_ = 0, XYPOS top_ = 0, XYPOS right_ = 0, XYPOS bottom_ = 0 ) :
		left( left_ ), top( top_ ), right( right_ ), bottom( bottom_ ) {
	}

	bool operator==( Rect& rc ) {
		return ( rc.left == left ) && ( rc.right == right ) &&
			   ( rc.top == top ) && ( rc.bottom == bottom );
	}
	bool Contains( Point pt ) {
		return ( pt.x >= left ) && ( pt.x <= right ) &&
			   ( pt.y >= top ) && ( pt.y <= bottom );
	}
	bool Contains( Rect& rc ) {
		return ( rc.left >= left ) && ( rc.right <= right ) &&
			   ( rc.top >= top ) && ( rc.bottom <= bottom );
	}
	bool Intersects( Rect& other ) {
		return ( right > other.left ) && ( left < other.right ) &&
			   ( bottom > other.top ) && ( top < other.bottom );
	}
	void Move( XYPOS xDelta, XYPOS yDelta ) {
		left += xDelta;
		top += yDelta;
		right += xDelta;
		bottom += yDelta;
	}
	XYPOS Width() {
		return right - left;
	}
	XYPOS Height() {
		return bottom - top;
	}
	bool Empty() {
		return ( Height() <= 0 ) || ( Width() <= 0 );
	}
};

/**
 * Holds a desired RGB colour.
 */
class Color {
	UINT32 co;
public:
	Color( UINT32 lcol = 0 ) {
		co = lcol;
	}

	Color( UINT32 red, UINT32 green, UINT32 blue ) {
		Set( red, green, blue );
	}
	Color( UINT32 red, UINT32 green, UINT32 blue, UINT32 alpha ) {
		Set( red, green, blue, alpha );
	}

	bool operator==( const Color& other ) const {
		return co == other.co;
	}

	void Set( UINT32 lcol ) {
		co = lcol;
	}

	void Set( UINT32 red, UINT32 green, UINT32 blue ) {
		co = red | ( green << 8 ) | ( blue << 16 );
	}
	void Set( UINT32 red, UINT32 green, UINT32 blue, UINT32 alpha ) {
		co = red | ( green << 8 ) | ( blue << 16 ) | ( alpha << 24 );
	}
	static inline UINT32 ValueOfHex( char ch ) {
		if ( ch >= '0' && ch <= '9' ) {
			return ch - '0';
		} else if ( ch >= 'A' && ch <= 'F' ) {
			return ch - 'A' + 10;
		} else if ( ch >= 'a' && ch <= 'f' ) {
			return ch - 'a' + 10;
		} else {
			return 0;
		}
	}

	//TODO support Alpha
	void Set( const char* val ) {
		if ( *val == '#' ) {
			val++;
		}
		UINT32 r = ValueOfHex( val[0] ) * 16 + ValueOfHex( val[1] );
		UINT32 g = ValueOfHex( val[2] ) * 16 + ValueOfHex( val[3] );
		UINT32 b = ValueOfHex( val[4] ) * 16 + ValueOfHex( val[5] );
		Set( r, g, b );
	}

	UINT32 AsLong() const {
		return co;
	}

	UINT32 GetRed() {
		return co & 0XFF;
	}

	UINT32 GetGreen() {
		return ( co >> 8 ) & 0XFF;
	}

	UINT32 GetBlue() {
		return ( co >> 16 ) & 0XFF;
	}
	UINT32 GetAlpha() {
		return ( co >> 24 ) & 0XFF;
	}
};
class ColourAllocated {
	long coAllocated;

public:

	ColourAllocated( long lcol = 0 ) {
		coAllocated = lcol;
	}

	void Set( long lcol ) {
		coAllocated = lcol;
	}

	long AsLong() const {
		return coAllocated;
	}
};
struct ColourPair {
	Color desired;
	ColourAllocated allocated;

	ColourPair( Color desired_ = Color( 0, 0, 0 ) ) {
		desired = desired_;
		allocated.Set( desired.AsLong() );
	}
	void Copy() {
		allocated.Set( desired.AsLong() );
	}
};
struct FontParameters {
	string faceName;
	float size;
	int weight;
	bool italic;
	int extraFontFlag;
	int technology;
	int characterSet;

	FontParameters(
		const char* faceName_,
		float size_ = 10,
		int weight_ = 400,
		bool italic_ = false,
		int extraFontFlag_ = 0,
		int technology_ = 0,
		int characterSet_ = 0 ) :

		size( size_ ),
		weight( weight_ ),
		italic( italic_ ),
		extraFontFlag( extraFontFlag_ ),
		technology( technology_ ),
		characterSet( characterSet_ ) {
		faceName = faceName_;
	}

};

class Font {
protected:
	FontID fid;
#if PLAT_WX
	int ascent;
#endif
	// Private so Font objects can not be copied
	Font(const Font &);
	Font &operator=(const Font &);
public:
	Font();
	virtual ~Font();

	virtual void Create(const char *faceName, int characterSet, int size,
		bool bold, bool italic, int extraFontFlag=0);
	virtual void Release();

	FontID GetID() { return fid; }
	// Alias another font - caller guarantees not to Release
	void SetID(FontID fid_) { fid = fid_; }
#if PLAT_WX
	void SetAscent(int ascent_) { ascent = ascent_; }
#endif
	friend class Surface;
	friend class SurfaceImpl;
};

class Window;
class Palette {
	int used;
	int size;
	ColourPair* entries;
	// Private so Palette objects can not be copied
	Palette( const Palette& );
	Palette& operator=( const Palette& );
public:
	void* hpal;
	bool allowRealization;

	Palette();
	~Palette();

	void Release();

	/**
	 * This method either adds a colour to the list of wanted colours (want==true)
	 * or retrieves the allocated colour back to the ColourPair.
	 * This is one method to make it easier to keep the code for wanting and retrieving in sync.
	 */
	void WantFind( ColourPair& cp, bool want );

	void Allocate( Window& w );
};
class Surface {
private:
	// Private so Surface objects can not be copied
	Surface( const Surface& ) {}
	Surface& operator=( const Surface& ) {
		return *this;
	}
public:
	Surface() {}
	virtual ~Surface() {}
	static Surface* Allocate();

	virtual void Init( WindowID wid ) = 0;
	virtual void Init( SurfaceID sid, WindowID wid ) = 0;
	virtual void InitPixMap( int width, int height, Surface* surface_, WindowID wid ) = 0;

	virtual void Release() = 0;
	virtual bool Initialised() = 0;
	virtual void PenColour( ColourAllocated fore ) = 0;
	virtual int LogPixelsY() = 0;
	virtual int DeviceHeightFont( int points ) = 0;
	virtual void MoveTo( int x_, int y_ ) = 0;
	virtual void LineTo( int x_, int y_ ) = 0;
	virtual void Polygon( Point* pts, int npts, ColourAllocated fore, ColourAllocated back ) = 0;
	virtual void RectangleDraw( Rect rc, ColourAllocated fore, ColourAllocated back ) = 0;
	virtual void FillRectangle( Rect rc, ColourAllocated back ) = 0;
	virtual void FillRectangle( Rect rc, Surface& surfacePattern ) = 0;
	virtual void RoundedRectangle( Rect rc, ColourAllocated fore, ColourAllocated back ) = 0;
	virtual void AlphaRectangle( Rect rc, int cornerSize, ColourAllocated fill, int alphaFill,
								 ColourAllocated outline, int alphaOutline, int flags ) = 0;
	virtual void Ellipse( Rect rc, ColourAllocated fore, ColourAllocated back ) = 0;
	virtual void Copy( Rect rc, Point from, Surface& surfaceSource ) = 0;

	virtual void DrawTextNoClip( Rect rc, Font& font_, int ybase, const char* s, int len, ColourAllocated fore, ColourAllocated back ) = 0;
	virtual void DrawTextClipped( Rect rc, Font& font_, int ybase, const char* s, int len, ColourAllocated fore, ColourAllocated back ) = 0;
	virtual void DrawTextTransparent( Rect rc, Font& font_, int ybase, const char* s, int len, ColourAllocated fore ) = 0;
	virtual void MeasureWidths( Font& font_, const char* s, int len, int* positions ) = 0;
	virtual int WidthText( Font& font_, const char* s, int len ) = 0;
	virtual int WidthChar( Font& font_, char ch ) = 0;
	virtual int Ascent( Font& font_ ) = 0;
	virtual int Descent( Font& font_ ) = 0;
	virtual int InternalLeading( Font& font_ ) = 0;
	virtual int ExternalLeading( Font& font_ ) = 0;
	virtual int Height( Font& font_ ) = 0;
	virtual int AverageCharWidth( Font& font_ ) = 0;

	virtual int SetPalette( Palette* pal, bool inBackGround ) = 0;
	virtual void SetClip( Rect rc ) = 0;
	virtual void FlushCachedState() = 0;

	virtual void SetUnicodeMode( bool unicodeMode_ ) = 0;
	virtual void SetDBCSMode( int codePage ) = 0;
};


/**
 * A simple callback action passing one piece of untyped user data.
 */
typedef void ( *CallBackAction )( void* );

/**
 * Class to hide the details of window manipulation.
 * Does not own the window which will normally have a longer life than this object.
 */
class Window {
public:
	enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand };
protected:
	WindowID wid;
public:
	Window() : wid( 0 ), cursorLast( cursorInvalid ) {
	}
	Window( const Window& source ) : wid( source.wid ), cursorLast( cursorInvalid ) {
	}
	virtual ~Window();
	Window& operator=( WindowID wid_ ) {
		wid = wid_;
		return *this;
	}
	WindowID GetID() const {
		return wid;
	}
	bool Created() const {
		return wid != 0;
	}
	void Destroy();
	bool HasFocus();
	Rect GetPosition();
	void SetPosition( Rect rc );
	void SetPositionRelative( Rect rc, Window relativeTo );
	Rect GetClientPosition();
	void Show( bool show = true );
	void InvalidateAll();
	void InvalidateRectangle( Rect rc );
	virtual void SetFont( Font& font );

	void SetCursor( Cursor curs );
	void SetTitle( const char* s );
	Rect GetMonitorRect( Point pt );
private:
	Cursor cursorLast;
};

/**
 * Listbox management.
 */

class ListBox : public Window {
public:
	ListBox();
	virtual ~ListBox();
	static ListBox *Allocate();

	virtual void SetFont(Font &font)=0;
	virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_)=0;
	virtual void SetAverageCharWidth(int width)=0;
	virtual void SetVisibleRows(int rows)=0;
	virtual int GetVisibleRows() const=0;
	virtual Rect GetDesiredRect()=0;
	virtual int CaretFromEdge()=0;
	virtual void Clear()=0;
	virtual void Append(char *s, int type = -1)=0;
	virtual int Length()=0;
	virtual void Select(int n)=0;
	virtual int GetSelection()=0;
	virtual int Find(const char *prefix)=0;
	virtual void GetValue(int n, char *value, int len)=0;
	virtual void RegisterImage(int type, const char *xpm_data)=0;
	virtual void ClearRegisteredImages()=0;
	virtual void SetDoubleClickAction(CallBackAction, void *)=0;
	virtual void SetList(const char* list, char separator, char typesep)=0;
};

/**
 * Menu management.
 */
class Menu {
	MenuID mid;
public:
	Menu();
	MenuID GetID() { return mid; }
	void CreatePopUp();
	void Destroy();
	void Show(Point pt, Window &w);
};



/**
 * Dynamic Library (DLL/SO/...) loading
 */
class DynamicLibrary {
public:
	virtual ~DynamicLibrary() {}

	/// @return Pointer to function "name", or NULL on failure.
	virtual Function FindFunction( const char* name ) = 0;

	/// @return true if the library was loaded successfully.
	virtual bool IsValid() = 0;

	/// @return An instance of a DynamicLibrary subclass with "modulePath" loaded.
	static DynamicLibrary* Load( const char* modulePath );
};

/**
 * Platform class used to retrieve system wide parameters such as double click speed
 * and chrome colour. Not a creatable object, more of a module with several functions.
 */
class Platform {
	// Private so Platform objects can not be copied
	Platform( const Platform& ) {}
	Platform& operator=( const Platform& ) {
		return *this;
	}
public:
	// Should be private because no new Platforms are ever created
	// but gcc warns about this
	Platform() {}
	~Platform() {}
	static Color Chrome();
	static Color ChromeHighlight();
	static const char* DefaultFont();
	static int DefaultFontSize();
	static unsigned int DoubleClickTime();
	static bool MouseButtonBounce();
	static void DebugDisplay( const char* s );
	static bool IsKeyDown( int key );
	static long SendScintilla(
		WindowID w, unsigned int msg, unsigned long wParam = 0, long lParam = 0 );
	static long SendScintillaPointer(
		WindowID w, unsigned int msg, unsigned long wParam = 0, void* lParam = 0 );
	static bool IsDBCSLeadByte( int codePage, char ch );
	static int DBCSCharLength( int codePage, const char* s );
	static int DBCSCharMaxLength();

	// These are utility functions not really tied to a platform
	static int Minimum( int a, int b );
	static int Maximum( int a, int b );
	// Next three assume 16 bit shorts and 32 bit longs
	static long LongFromTwoShorts( short a, short b ) {
		return ( a ) | ( ( b ) << 16 );
	}
	static short HighShortFromLong( long x ) {
		return static_cast<short>( x >> 16 );
	}
	static short LowShortFromLong( long x ) {
		return static_cast<short>( x & 0xffff );
	}
	static void DebugPrintf( const char* format, ... );
	static bool ShowAssertionPopUps( bool assertionPopUps_ );
	static void Assert( const char* c, const char* file, int line );
	static int Clamp( int val, int minVal, int maxVal );
};


struct Sci_CharacterRange {
	long cpMin;
	long cpMax;
};

struct Sci_TextRange {
	struct Sci_CharacterRange chrg;
	char* lpstrText;
};

struct Sci_TextToFind {
	struct Sci_CharacterRange chrg;
	char* lpstrText;
	struct Sci_CharacterRange chrgText;
};

#define CharacterRange Sci_CharacterRange
#define TextRange Sci_TextRange
#define TextToFind Sci_TextToFind

typedef void* Sci_SurfaceID;

struct Sci_Rectangle {
	int left;
	int top;
	int right;
	int bottom;
};

/* This structure is used in printing and requires some of the graphics types
 * from Platform.h.  Not needed by most client code. */

struct Sci_RangeToFormat {
	Sci_SurfaceID hdc;
	Sci_SurfaceID hdcTarget;
	struct Sci_Rectangle rc;
	struct Sci_Rectangle rcPage;
	struct Sci_CharacterRange chrg;
};

#define RangeToFormat Sci_RangeToFormat

struct Sci_NotifyHeader {
	/* Compatible with Windows NMHDR.
	 * hwndFrom is really an environment specific window handle or pointer
	 * but most clients of Scintilla.h do not have this type visible. */
	void* hwndFrom;
	uptr_t idFrom;
	unsigned int code;
};

#define NotifyHeader Sci_NotifyHeader

struct SCNotification {
	struct Sci_NotifyHeader nmhdr;
	int position;
	/* SCN_STYLENEEDED, SCN_DOUBLECLICK, SCN_MODIFIED, SCN_MARGINCLICK, */
	/* SCN_NEEDSHOWN, SCN_DWELLSTART, SCN_DWELLEND, SCN_CALLTIPCLICK, */
	/* SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, SCN_HOTSPOTRELEASECLICK, */
	/* SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */
	/* SCN_USERLISTSELECTION, SCN_AUTOCSELECTION */

	int ch;		/* SCN_CHARADDED, SCN_KEY */
	int modifiers;
	/* SCN_KEY, SCN_DOUBLECLICK, SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, */
	/* SCN_HOTSPOTRELEASECLICK, SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */

	int modificationType;	/* SCN_MODIFIED */
	const char* text;
	/* SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION, SCN_URIDROPPED */

	int length;		/* SCN_MODIFIED */
	int linesAdded;	/* SCN_MODIFIED */
	int message;	/* SCN_MACRORECORD */
	uptr_t wParam;	/* SCN_MACRORECORD */
	sptr_t lParam;	/* SCN_MACRORECORD */
	int line;		/* SCN_MODIFIED */
	int foldLevelNow;	/* SCN_MODIFIED */
	int foldLevelPrev;	/* SCN_MODIFIED */
	int margin;		/* SCN_MARGINCLICK */
	int listType;	/* SCN_USERLISTSELECTION */
	int x;			/* SCN_DWELLSTART, SCN_DWELLEND */
	int y;		/* SCN_DWELLSTART, SCN_DWELLEND */
	int token;		/* SCN_MODIFIED with SC_MOD_CONTAINER */
	int annotationLinesAdded;	/* SCN_MODIFIED with SC_MOD_CHANGEANNOTATION */
	int updated;	/* SCN_UPDATEUI */
};

struct SearchResultMarking {
	long _start;
	long _end;
};

struct SearchResultMarkings {
	long _length;
	SearchResultMarking* _markings;
};


void Platform_Initialise(void * hInstance);
void Platform_Finalise();

}



